package com.apexsoft.assets.base.model;


import cn.hutool.core.io.FileUtil;
import cn.hutool.core.io.IORuntimeException;
import cn.hutool.core.io.IoUtil;
import cn.hutool.core.lang.UUID;
import lombok.extern.slf4j.Slf4j;

import javax.imageio.ImageIO;
import java.awt.image.BufferedImage;
import java.io.*;
import java.util.Locale;

/**
 * 缓存文件
 * 创建缓存文件初始化时写入文件，其后不允许对临时文件进行修改
 * inputstram流实现了AutoCloseable方法，当在try-catch块结束后会自动关闭
 */

@Slf4j
public final class TmpFile extends InputStream{

    /** 是否关闭 */
    private volatile boolean closed = false;

    /** Field  临时文件*/
    private final File tempFile;

    /** Field  输入流*/
    private InputStream fis;

    /** Field  标识文件的UUID 初始化时创建，不允许修改*/
    private final String uuid;

    /** Field  文件名*/
    private final String fileName;

    /**
     * Constructs
     *
     */
    public TmpFile(BufferedImage image, String fileName) {
        this.uuid = UUID.fastUUID().toString(true);
        this.fileName = fileName;
        this.tempFile = new File("temp"+File.separator+uuid);
        String extName = FileUtil.extName(fileName).toLowerCase(Locale.ROOT);
        try{
            ImageIO.write(image, extName, tempFile);
        }catch (IORuntimeException | IOException ioe){
            log.error("临时文件创建失败,请检查你的权限和磁盘空间!",ioe);
            throw new RuntimeException("临时文件空间创建失败，可能磁盘容量不足");
        }
    }

    /**
     * Constructs
     *
     */
    public TmpFile(InputStream in, String fileName) {
        this.uuid = UUID.fastUUID().toString(true);
        this.fileName = fileName;
        this.tempFile = new File("temp"+File.separator+uuid);
        try{
            //hutool写入时会自动关闭流
            FileUtil.writeFromStream(in,tempFile);
        }catch (IORuntimeException ioe){
            log.error("临时文件创建失败,请检查你的权限和磁盘空间!",ioe);
            throw new RuntimeException("临时文件空间创建失败，可能磁盘容量不足");
        }
    }

    /**
     * 读取缓存文件所有数据
     * @return
     */
    public byte[] readBytes(){
        init();
        return IoUtil.readBytes(fis,true);
    }

    /**
     * 初始化，每次使用临时文件前请调用此方法
     */
    public void init(){
        try {
            if(fis != null){
                fis.close();
            }
            fis = new FileInputStream(tempFile);
        } catch (FileNotFoundException e) {
            throw new RuntimeException(e);
        } catch (IOException e) {
            throw new RuntimeException("重置缓存文件输入流失败");
        }

    }

    public String getFileName(){
        return fileName;
    }

    public long getFileLength(){
        return tempFile.length();
    }

    @Override
    public int available() throws IOException {
        return fis.available();
    }

    @Override
    public void close() throws IOException {
        if(closed){
            return;
        }
        try{
            if(fis != null){
                fis.close();
            }
        }finally {
            closed = FileUtil.del(tempFile);
        }
    }

    @Override
    public synchronized void mark(int readlimit) {
        fis.mark(readlimit);
    }

    @Override
    public boolean markSupported() {
        return fis.markSupported();
    }

    @Override
    public int read() throws IOException {
        return fis.read();
    }

    @Override
    public int read(byte[] b, int off, int len) throws IOException {
        return fis.read(b, off, len);
    }

    @Override
    public synchronized void reset() throws IOException {
        fis.reset();
    }

    @Override
    public long skip(long n) throws IOException {
        return fis.skip(n);
    }

    @Override
    protected void finalize() throws Throwable {
        try{
            this.close();
        }finally {
            super.finalize();
        }
    }
}

